<?php

namespace App\Controllers;

use Framework\Database;
use Framework\Validation;
use Framework\Session;
use Framework\Authorisation;
use Framework\Middleware\Authorise;

class ListingController
{
    protected $db;

    public function __construct()
    {
        $config = require basePath('config/db.php');
        $this->db = new Database($config);
    }
/**
 * 展示所有岗位
 * 
 * @return void
 */
    public function index()
    {
        $listings = $this->db->query('SELECT * FROM listing ORDER BY created_at DESC')->fetchAll();

        loadView('listings/index',[
            'listings' => $listings
        ]);
    }

   /**
    * 展示创建职位表单
    *
    *@return void
    */
    public function create()
    {
        loadView('listings/create');
    }

    /**
     * 展示单一岗位页面
     * 
     * @return void
     */
    public function show($params)
    {
        $id = $params['id'] ?? '';

        $params = [
            'id' => $id
        ];

        $listing = $this->db->query('SELECT * FROM listing WHERE id = :id',$params)->fetch();

        //检查 listing 是否存在
        if (!$listing){
            ErrorController::notFound('该岗位不存在！');
            return;
        }

        loadView('listings/show',[
            'listing' => $listing
        ]);
    }


    /**
     * 在数据库中存储数据
     * 
     * 该函数首先定义了一个允许从表单收集的字段列表。然后，它从 $_POST 全局数组中提取这些允许的字段的数据。
     * 接着，为新的列表数据指定一个默认的用户 ID,并且对数据库进行清洗。
     * 然后，定义必须填写的字段列表，遍历这些字段检查是否为空或者是否通过字符串验证。
     * 如果有任何问题错误，将错误信息返回并重新加载试图；如果没有需错误，则显示成功消息。
     * 
     * @return void 该函数没有返回值
     */
    public function store()
    {
        $allowedFields = ['title','description','salary','tags','company','address','city','province','phone',
        'email','requirements','benefits'];

        //从$_POST中提取允许的字段
        $newListingData = array_intersect_key($_POST,array_flip($allowedFields));

        //设置用户ID
        $newListingData['user_id'] = Session::get('user')['id'];

        //清洗数据
        $newListingData = array_map('sanitize',$newListingData);

        //定义必须的字段
        $requiredFields = ['title','description','email','city','province'];

        //检查必须的字段
        $errors = [];
        foreach ($requiredFields as $field){
            if(empty($newListingData[$field]) || !Validation::string($newListingData[$field])){
                $errors[$field] = ucfirst($field) . '为必须项';
            }
        }

        //处理可能的错误
        if(!empty($errors)){
            loadView('listings/create',[
                'errors' => $errors,
                'listing' => $newListingData
            ]);
        }else{
            //初始化一个数组来收集所有字段名称，为构建SQL查询做准备
            $fields = [];

            //遍历 $newListingData 数组，收集字段名称
            foreach ($newListingData as $field => $value) {
                // 向 $fields 数组的末尾添加一个新元素
                $fields[] = $field;
            }

            // 使用 implode 函数将字段名称数组转换为字符串，用逗号分隔
            $fields = implode(',',$fields);

            //初始化一个数组来收集对应的占位符
            $values = [];

            // 遍历 $newListingData 数组，为每个字段生成一个占字符，并处理空字符串为 null
            foreach ($newListingData as $field => $value){
                if ($value === ''){
                    $newListingData[$field] = null;
                }
                $values[] = ':' . $field;
            }
            
            //使用 implode 函数将占位符数组转换为字符串，用逗号分隔
            $values = implode(',', $values);

            //构建 SQL 插入语句
            $query = "INSERT INTO listing ({$fields}) VALUES ({$values})";

            //执行 SQL 插入操作
            $this->db->query($query,$newListingData);

            Session::setFlashMessage('success_message','已成功创建职位！');

            //重定向列表页面
            redirect('/listings');
        }
    }

    /**
     * 删除一个列表
     * 
     * 该方法首先通过参数获取列表项的ID.然后，使用这个ID来查询数据库中是否存在该列表项
     * 如果查询结果显示列表项存在，那么它将执行删除操作；如果不存在，则显示错误信息并终止操作
     * 删除操作成功后，函数将重新向用户到列表页面
     * 
     * @param array $params 包含必要参数的数组，如列表项的ID
     * @return void 该方法没有返回值
     */
    public function destroy($params)
    {
        //从参数中获取列表的ID
        $id = $params['id'];

        //准备用于数据库查询的参数
        $params = [
            'id' => $id
        ];

        //查询数据库以确认列表项是否存在
        $listing = $this->db->query('SELECT * FROM listing WHERE id = :id', $params)->fetch();

        //如果查询结果为空，即列表项不存在
        if(!$listing){
            //调用错误控制器处理找不到类表项的情况
            ErrorController::notFound('职位不存在！');
            return;
        }

        if (!Authorisation::isOwner($listing->user_id))
        {
            
            inspect($_SESSION);
            Session::setFlashMessage('error_message','你没有权限修改此职位!');
            // $_SESSION['error_message'] = '你没有权限删除此职位！';
            return redirect('/listings/' . $listing->id);
        }

        //执行删除操作
        $this->db->query('DELETE FROM listing WHERE id = :id',$params);

        //设置提示信息
        // $_SESSION['success_message'] = '删除职位成功！';
        Session::setFlashMessage('error_message','删除职位成功！');

        //删除成功后重定向到列表页面
        redirect('/listings');
    }

    /**
     * 显示列表项编辑表单
     * 
     * 该方法用于加载特定列表项的编辑表单。它首先尝试从列表中获取列表项的ID
     * 使用这个ID从数据库中查询相应的列表项数据。如果找到了对应的列表项，他将加载编辑视图并传递列表项数据
     * 如果没有找到，他将调用错误控制器显示“未找到列表项”的错误
     * 
     * @param array $params 包含必要参数的数组，例如列表项的ID
     * @return void 该方法没有返回值
     */
    public function edit($params)
    {
        //尝试从参数中获取ID,如果没有提供，则默认为字符串
        $id = $params['id'] ?? '';

        //准备用于数据库查询的参数
        $params = [
            'id' => $id
        ];

        //查询数据库，获取指定ID列表项数据
        $listing = $this->db->query('SELECT * FROM listing WHERE id = :id',$params)->fetch();

        //检查查询结果，确保列表项存在
        if(!$listing){
            //如果未找到列表项，调用错误控制器并返回
            ErrorController::notFound('职位不存在！');
            return;
        }

        //授权
        
        if (!Authorisation::isOwner($listing->user_id))
        {
            Session::setFlashMessage('error_message','你没有权限修改此职位!');
            return redirect('/listings/' . $listing->id);
        }

        //如果列表项存在，加载编辑试图并传递列表数据
        loadView('listings/edit',[
            'listing' => $listing
        ]); 
    }

    /**
     * 更新列表数据
     */
    public function update($params)
    {
        //从参数中尝试获取列表ID,如果没有提供，则默认为空字符串
        $id = $params['id'] ?? '';

        //准备用于数据库查询的参数
        $params = [
            'id' => $id
        ];

        //查询数据库以确认列表项是否存在
        $listing = $this->db->query('SELECT * FROM listing WHERE id = :id',$params)->fetch();

        //如果列表项不存在
        if(!$listing)
        {
            //调用错误控制器并结束方法执行
            ErrorController::notFound('职位不存在！');
            return;
        }

       //授权
        if (!Authorisation::isOwner($listing->user_id))
        {
            Session::setFlashMessage('error_message','你没有权限修改此职位!');
            return redirect('/listings/' . $listing->id);
        }

         //定义可以从表单接收的字段列表
        $allowedFields = ['title','description','salary','tags','company','address','city','province','phone',
        'email','requirements','benefits'];

        //过滤并仅保留允许字段
        $updateValus = array_intersect_key($_POST,array_flip($allowedFields));

        //对过滤后的数据进行清洗
        $updateValus = array_map('sanitize',$updateValus);

        //定义必须填写的字段列表
        $requiredFields = ['title','description','salary','email','city','province'];

        //初始化错误收集
        $errors = [];
        
        //检查必填字段是否已经填写且符合要求
        foreach ($requiredFields as $field)
        {
            if(empty($updateValus[$field]) || !Validation::string($updateValus[$field]))
            {
                $errors[$field] = ucfirst($field) . "为必需项!";
            }
        }
    
        //如果存在错误
        if(!empty($errors))
        {
            //重新加载视图
            loadView('listings/edit',[
                'listing' => $listing,
                'errors' => $errors
            ]);
            exit;
        }
        else{
            //构建SQL更新语句中的字段赋值部分
            $updateFields = [];
            foreach (array_keys($updateValus) as $field) {
                $updateFields[] = "{$field} = :{$field}";
            }

            //将字段赋值部分合成字符串
            $updateFields = implode(', ',$updateFields);

            //构建完整的SQL更新语句
            $updateQuery = "UPDATE listing SET $updateFields WHERE id = :id";

            //在更新数据中包括ID
            $updateValus['id'] = $id;
            //执行SQL更新操作
            $this->db->query($updateQuery,$updateValus);

            //设置成功消息
            Session::setFlashMessage('success_message','职位信息已更新!');

            //重新定向到列表详情页面
            redirect('/listings/' . $id);
        }
    }
    /**
     * 根据关键词和地点搜索列表
     */
    public function search()
    {
        $keywords = isset($_GET['keywords']) ? trim($_GET['keywords']) : '';
        $location = isset($_GET['location']) ? trim($_GET['location']) : '';
            
        $query = "SELECT * FROM listing WHERE
                 (title LIKE :keywords OR description LIKE :keywords OR 
                 tags LIKE :keywords OR company LIKE :keywords) AND
                 (city LIKE :location OR province LIKE :location)";
            
        $params = [
            'keywords' => "%{$keywords}%",
            'location' => "%{$location}%"
        ];
            
        $listings = $this->db->query($query, $params)->fetchAll();
            
        loadView('/listings/index',[
            'listings' => $listings,
            'keywords' => $keywords,
            'location' => $location
        ]);
    }
    
}